package Game;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.io.File;
import java.io.Serializable;

import javax.imageio.ImageIO;
import javax.swing.*;

import GUIInterfaces.OregonPanel;
import GUIInterfaces.OregonWindow;

import java.util.*;

/**
 * 
 */

/**
 * @author William Kurkian
 *	This panel works by passing it the gamedriver and generating the store.
 *	It expects the window above it to implement OregonWindow and it has oregon panel
 */
public class StorePanel extends JPanel implements ActionListener,OregonPanel,Serializable {
	
	GameDriver gd;
	Caravan caravan;
	Store store;
	OregonWindow parent;
	BufferedImage background;
	HashMap<Integer,BufferedImage> itemImages;
	HashMap<Integer,BufferedImage> itemImagesHighlighted;
	JButton buy = new JButton();
	JButton sell = new JButton();
	JButton steal = new JButton();
	JButton work = new JButton();
	JLabel day = new JLabel("1");
	JLabel food = new JLabel("0");
	JLabel money = new JLabel("0");
	JLabel weightLeft = new JLabel("0");
	JLabel quantity = new JLabel("Quantity: ");
	JButton done = new JButton();
	
	JButton storeLeft = new JButton();
	JButton storeRight = new JButton();
	
	JButton playerLeft = new JButton();
	JButton playerRight = new JButton();
	
	JButton[] storeItemButtons = new JButton[6];
	private int[] storeItems = new int[6]; 
	private JButton[] playerItemButtons = new JButton[6];
	private int[] playerItems = new int[6];
	private int weight = 0;
	private int playerIndex = 0;
	private int storeIndex = 0;
	private int storeChosen = -1;
	private int playerChosen = -1;
	
	private Inventory storeInventory;
	private Inventory playerInventory;
	
	/*
	 * The constructor creates the components and initializes everything.
	 */
	public StorePanel(OregonWindow parent) {
		this.parent = parent;
		this.setLayout(null);
		
		configureButton(buy,new Rectangle(24,516,124,50));
		configureButton(sell,new Rectangle(170,516,124,50));
		configureButton(steal,new Rectangle(315,516,124,50));
		configureButton(work,new Rectangle(474,516,124,50));
		configureButton(done,new Rectangle(618,516,124,50));
		configureButton(storeLeft,new Rectangle(322,193,53,49));
		configureButton(storeRight,new Rectangle(378,193,53,49));
		configureButton(playerLeft,new Rectangle(318,316,53,49));
		configureButton(playerRight,new Rectangle(382,316,53,49));
		
		configureLabel(day, new Rectangle(584,34,100,25));
		configureLabel(food, new Rectangle(598,47,100,25));
		configureLabel(money, new Rectangle(618,77,100,25));
		configureLabel(weightLeft, new Rectangle(668,99,80,25));
		configureLabel(quantity, new Rectangle(667,59,100,25));
		
		int x = 175;
		int y = 100;
		for (int i = 0; i < storeItems.length; i++) {
			storeItemButtons[i] = new JButton();
			configureButton(storeItemButtons[i],new Rectangle(x+i*75,y,75,75));
			add(storeItemButtons[i]);
		}
		for (int i = 0; i < playerItems.length; i++) {
			playerItemButtons[i] = new JButton();
			configureButton(playerItemButtons[i],new Rectangle(x+i*75,y+125,75,75));
			add(playerItemButtons[i]);
		}
		add(buy);
		add(sell);
		add(steal);
		add(work);
		add(day);
		add(money);
		add(food);
		add(weightLeft);
		add(done);
		add(playerLeft);
		add(playerRight);
		add(storeLeft);
		add(storeRight);
		itemImages = new HashMap<Integer,BufferedImage>();
		itemImagesHighlighted = new HashMap<Integer,BufferedImage>();
		String folder = System.getProperty("user.dir")+ File.separator + "images" + File.separator;
		try {
			background = ImageIO.read(new File(folder+"store.png"));
			ItemList items = gd.getItemList();
			int ids = items.size();
			for (int i = 0 ; i  < ids; i++)  {
				String itemFile = items.getItemPictureFile(i);
				String itemhFile = itemFile.substring(0, itemFile.length()-4) + 'h'+".png";
				System.out.println(itemhFile);
				try {
					itemImages.put(i, ImageIO.read(new File(folder+itemFile)));
					itemImagesHighlighted.put(i, ImageIO.read(new File(folder +itemhFile)));
				} catch(Exception e) {
					System.out.println("Image: " + itemFile + " " + itemhFile + " did not load properly.");
					
				}
			}
		} catch(Exception e) {
			JOptionPane.showMessageDialog(this, e.getMessage());
			System.out.println("The store bckground did not load properly.");
		}
		
	}

	/**
	 * Method to configure buttons. It makes them invisible and sets their bounds to rectangle.
	 * @param button
	 * @param rectangle
	 */
	private void configureButton(JButton button, Rectangle rectangle) {
		button.setBounds(rectangle);
		button.setOpaque(false);
		button.setContentAreaFilled(false);
		button.setBorderPainted(false);
		button.addActionListener(this);
		
	}

	/**
	 * This method configures the passed in label.
	 * @param label
	 * @param rectangle
	 */
	private void configureLabel(JLabel label, Rectangle rectangle) {
		label.setBounds(rectangle);
		label.setFont(new Font(label.getFont().getName(), label.getFont().getStyle(),20));
	}
	
	public void paintComponent(Graphics g) {
		g.drawImage(background,0,0,null);
		g.setFont(new Font(Font.SERIF,Font.BOLD,20));
		for (int i = 0 ; i < playerItemButtons.length; i++) {
			
			if (playerItems[i] != -1) {
				//g.setColor(Color.white);
				//g.fillRect(playerItemButtons[i].getX(), playerItemButtons[i].getY()+playerItemButtons[i].getHeight()-20, 20, 30);
				BufferedImage icon;
				int item = playerItems[i];
				if (i != playerChosen)
					icon = itemImages.get(item);
				else
					icon = itemImagesHighlighted.get(item);
				g.drawImage(icon,playerItemButtons[i].getX(),playerItemButtons[i].getY(),null);
				g.setColor(Color.black);
				g.drawString(""+store.getPlayerInventory().getQuantityOf(playerItems[i]),playerItemButtons[i].getX()+28,playerItemButtons[i].getY()+playerItemButtons[i].getHeight()-4);
			}
		}
		for (int i = 0 ; i < storeItemButtons.length; i++) {
			if (storeItems[i] != -1) {
				//g.setColor(Color.white);
				//g.fillRect(storeItemButtons[i].getX(), storeItemButtons[i].getY()+storeItemButtons[i].getHeight()-20, 20, 30);
				BufferedImage icon;
				int item = storeItems[i];
				if (i != storeChosen)
					icon = itemImages.get(item);
				else
					icon = itemImagesHighlighted.get(item);
				g.drawImage(icon,storeItemButtons[i].getX(),storeItemButtons[i].getY(),null);
				
				g.setColor(Color.black);
				g.drawString(""+store.getStoreInventory().getQuantityOf(storeItems[i]),storeItemButtons[i].getX()+28,storeItemButtons[i].getY()+storeItemButtons[i].getHeight()-4);
			}
		}
	}
	/**
	 * This method allows the parent to set the game driver after initialization
	 * so the panel can be initalized before the caravan is ready.
	 * This is from the OregonPanel.
	 * @param gd
	 */
	public void setGameDriver(GameDriver gd) {
		this.gd = gd;
		caravan = gd.getCaravan();
		store = new Store(caravan);
		update();
		
	}
	
	/**
	 * This updates the panel state and caravan based on the current state of the store.
	 */
	private void update() {
		
		
		storeInventory = store.getStoreInventory();
		playerInventory = store.getPlayerInventory();
		int playerMoney = 0;
		playerMoney = caravan.getPlayerMoney();
		
		money.setText(playerMoney+"");
		weight = store.getCaravanWeight();
		weightLeft.setText(weight+"");
		food.setText(playerInventory.getRemainingFood()+"");
		day.setText(caravan.getDaysPast()+"");
		int i = 0;
		int j = storeIndex;
		int invItems = gd.getItemList().size();
		while ( i < storeItems.length && j < invItems) {
			if (storeInventory.getQuantityOf(j)>0) {
				storeItems[i] = j;
				
				i++;
				j++;
			} else  {
				storeItemButtons[i].setIcon(null);
				j++;
			}
		}
		for (; i < storeItems.length; i++) {
			storeItems[i] = -1;
		}
		i=0;
		j = playerIndex;
		while ( i < playerItems.length && j < invItems) {
			if (playerInventory.getQuantityOf(j)>0) {
				playerItems[i] = j;
				i++;
				j++;
			} else  {
				j++;
				//playerItemButtons[i].setIcon(null);
			}
		}
		for (; i < playerItems.length; i++) {
			playerItems[i] = -1;
		}
		gd.setCaravan(caravan);
		repaint();
	}
	
	@Override
	
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == done) {
			parent.done(this);
		}
		for (int i = 0; i < storeItemButtons.length; i++) {
			if (arg0.getSource() == storeItemButtons[i]) {
				storeChosen = i;
				
			}
		}
		for (int i = 0; i < playerItemButtons.length; i++) {
			if (arg0.getSource() == playerItemButtons[i]) {
				playerChosen = i;
				
			}
		}
		if (arg0.getSource() == storeLeft) {
			if (storeIndex > 0) {
				storeIndex--;
			}	
		} else if (arg0.getSource() == storeRight) {
			if (storeIndex  < gd.getItemList().size()-1) {
				storeIndex++;
			}
				
		} else if (arg0.getSource() == playerLeft) {
			if (playerIndex > 0) {
				playerIndex--;
			}	
		} else if (arg0.getSource() == playerRight) {
			if (playerIndex  < gd.getItemList().size()-1) {
				playerIndex++;
			}
		}
		else if (arg0.getSource() == buy) {
			
			if (storeChosen == -1 || storeItems[storeChosen]==-1) {
				JOptionPane.showMessageDialog(this, "You have not selected an item.");
				return;
			}
			int quantity;
			
			try {
				quantity = Integer.parseInt(JOptionPane.showInputDialog("How many do you want to buy?"));
			} catch (Exception e) {
				JOptionPane.showMessageDialog(this, "You entered an invalid number. Try again.");
				return;
			}
			int i = -1;
			while(i != 0) {
				int price;
				try {
					String tempPrice  = JOptionPane.showInputDialog("How much do you want to pay per item?");
					
					if (tempPrice == null)
						return;
					price = Integer.parseInt(tempPrice);
				} catch (Exception e) {
					JOptionPane.showMessageDialog(this, "You entered an invalid number. Try again.");
					continue;
				}
				if (price == JOptionPane.CANCEL_OPTION)
					return;
				i = store.buy(storeItems[storeChosen], quantity, price);
				if (i == 0)
					JOptionPane.showMessageDialog(this, "You have bought this item for " + price + " pesos each.");
				else if (i == -1)
					JOptionPane.showMessageDialog(this, "You don't have enough space for this item.");
				else if (i == -2) {
					JOptionPane.showMessageDialog(this, "You don't have enough money for this price.");
				} else if (i== -3) {
					JOptionPane.showMessageDialog(this, "The store doesn't have enough of these.");
					storeChosen=-1;
					return;
				} else  
					JOptionPane.showMessageDialog(this, "The store made a counter offer of: "+i);
				
			}
			
		} else if (arg0.getSource() == sell) {
			if (playerChosen == -1 || playerItems[playerChosen]==-1) {
				JOptionPane.showMessageDialog(this, "You have not selected an item.");
				return;
			}
			int quantity;
			try {
				quantity = Integer.parseInt(JOptionPane.showInputDialog("How many do you want to sell?"));
			} catch (Exception e) {
				JOptionPane.showMessageDialog(this, "You entered an invalid number. Try again.");
				return;
			}
			int sell = -1;
			while (sell != 0) {
				int price;
				try {
					String tempPrice  = JOptionPane.showInputDialog("How much do you want for each item?");
					if (tempPrice == null)
						return;
					price = Integer.parseInt(tempPrice);
				
				} catch (Exception e) {
					JOptionPane.showMessageDialog(this, "You entered an invalid number. Try again.");
					continue;
				}
				if (price == JOptionPane.CANCEL_OPTION)
					return;
				sell = store.sell(playerItems[playerChosen], quantity, price);
				System.out.println("The new sell price: "+sell+".");
				if (sell == 0)
					JOptionPane.showMessageDialog(this,"You have sold the item for " + price + " pesos each.");
				else if (sell == -1) {
					JOptionPane.showMessageDialog(this, "You don't have enough of this item.");
					playerChosen = -1;
					return;
				} else
					JOptionPane.showMessageDialog(this, "The store has made a counter offer of " + sell);
				
			}
		} else if (arg0.getSource() == steal) {
			if (storeChosen == -1 || storeItems[storeChosen]==-1) {
				JOptionPane.showMessageDialog(this, "You have not selected an item.");
				return;
			}
			int quantity;
			try {
				quantity = Integer.parseInt(JOptionPane.showInputDialog("How many do you want to steal?"));
			} catch (Exception e) {
				JOptionPane.showMessageDialog(this, "You entered an invalid number. Try again.");
				return;
			}
			
			boolean success = store.steal(storeItems[storeChosen], quantity);
			if (success) {
				
				JOptionPane.showMessageDialog(this, "You stole the item.");
				storeChosen = -1;
			} else if (!success) {
				JOptionPane.showMessageDialog(this, "You failed to steal. Your first party member was shot. Too bad for you.");
				if (store.getCharacters().size() == 0) {
					JOptionPane.showMessageDialog(this, "Your whole party is dead. You lose.");
					System.exit(-1);
				}
				
			}
		} else if (arg0.getSource() == work) {
			if (storeChosen == -1 || storeItems[storeChosen]==-1) {
				JOptionPane.showMessageDialog(this, "You have not selected an item.");
				return;
			}
			if (gd.getItemList().getItemWeight(storeItems[storeChosen])< store.getCaravanWeight()) {
				int quantity;
				try {
					quantity = Integer.parseInt(JOptionPane.showInputDialog("How many do you want to work for?"));
				} catch (Exception e) {
					JOptionPane.showMessageDialog(this, "You entered an invalid number. Try again.");
					return;
				}
				
				store.work(storeItems[storeChosen], quantity);
				JOptionPane.showMessageDialog(this, "You worked for " + store.getDaysOfWork(storeItems[storeChosen])*quantity+" days.");
				storeChosen=-1;
			} else {
				JOptionPane.showMessageDialog(this, "You don't have room for this. ");
			}
			
		}
		update();
	}

	public GameDriver getGameDriver() {
		return gd;
	}

	@Override
	public String getProperty() {
		// TODO Auto-generated method stub
		return null;
	}
}
